package com.xdf.docmanagementsystem.config;

import lombok.SneakyThrows;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter;
import org.apache.shiro.web.util.WebUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @program: doc-management-system
 * @description: JWT过滤器
 * @author: Zhang
 * @create: 2020-06-23 11:05
 **/
@Component
public class JWTFilter extends BasicHttpAuthenticationFilter {

    @Value("${jwt.anonymous.urls}")
    private String anonymousStr;

    /**
     * 登录用户验证
     *
     * @param request
     * @param response
     * @param mappedValue
     * @return
     */
    @SneakyThrows
    @Override
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
        //  判断请求头说上是否有Token
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        HttpServletResponse httpServletResponse = (HttpServletResponse) response;
        String contextPath = WebUtils.getPathWithinApplication(WebUtils.toHttp(request));
        String[] urls = anonymousStr.split(",");
        for (String url : urls) {
            if (contextPath.contains(url)) return true;
        }
        String token = getTokenFromRequest(httpServletRequest);
        if (StringUtils.isEmpty(token))
            token = getCookieToken(((HttpServletRequest) request).getCookies());
        if (StringUtils.isEmpty(token)) {
            responseError(response);
            return false;
        } else {
            try {
                this.executeLogin(request, response);
                return true;
            } catch (Exception e) {
                String msg = e.getMessage();
                return false;
            }
        }
    }

    @Override
    protected void issueSuccessRedirect(ServletRequest request, ServletResponse response) throws Exception {
        super.issueSuccessRedirect(request, response);
    }

    /**
     * 请求成功
     *
     * @param token
     * @param subject
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @Override
    protected boolean onLoginSuccess(AuthenticationToken token, Subject subject, ServletRequest request, ServletResponse response) throws Exception {
        HttpServletResponse httpServletResponse = (HttpServletResponse) response;
        httpServletResponse.setContentType("text/html;charset=UTF-8");
        httpServletResponse.setCharacterEncoding("UTF-8");
        httpServletResponse.setHeader("token", String.valueOf(token.getPrincipal()));
        httpServletResponse.sendRedirect("index");
        return true;
    }

    /**
     * 执行登录操作
     *
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @Override
    protected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception {
        String contextPath = WebUtils.getPathWithinApplication(WebUtils.toHttp(request));
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        String token = getTokenFromRequest(httpServletRequest);
        if (StringUtils.isEmpty(token))
            token = getCookieToken(((HttpServletRequest) request).getCookies());
        JWTToken jwtToken = new JWTToken(token);
        getSubject(request, response).login(jwtToken);
        return true;
    }

    /**
     * 创建Token
     *
     * @param request
     * @param response
     * @return
     */
    @Override
    protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) {
        HttpServletRequest req = (HttpServletRequest) request;
        String token = req.getHeader("token");
        return new JWTToken(token);
    }

    private void responseError(ServletResponse response) {
        HttpServletResponse httpServletResponse = (HttpServletResponse) response;
        try {
            httpServletResponse.setCharacterEncoding("UTF-8");
            response.setContentType("text/html;charset=UTF-8");
            httpServletResponse.sendRedirect("login");
        } catch (Exception e) {
        }
    }

    private String getCookieToken(Cookie[] cookies) {
        if (cookies == null || cookies.length <= 0) return null;
        for (Cookie cookie : cookies) {
            switch (cookie.getName()) {
                case "token":
                    return cookie.getValue();
            }
        }
        return null;
    }

    private String getTokenFromRequest(HttpServletRequest request) {
        String token = request.getHeader("token");
        if (StringUtils.isEmpty(token)) {
            token = request.getParameter("token");
        }
        return token;
    }
}
